package com.heima.admin.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.mapper.ChannelMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.exception.CustException;
import com.heima.feigns.ArticleFeign;
import com.heima.feigns.WemediaFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {


    @Autowired
    WemediaFeign wemediaFeign;

    @Value("${file.oss.web-site}")
     String webSite;
    /**
     * 自动审核
     * @param wmNewsId
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void autoScanByMediaNewsId(Integer wmNewsId) {
        log.info("自动审核发布方法被调用 ，当前审核发布的文章id===>{}",wmNewsId);
        //根据文章id 远程调用feign查询文章
        if (wmNewsId == null) {
            log.error("自动审核文章失败   文章id为空");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        ResponseResult<WmNews> wmNewsResult = wemediaFeign.findById(wmNewsId);
        if (wmNewsResult.getCode().intValue() != 0) {
            log.error("自动审核失败   远程查询文章信息失败，原因：{}",wmNewsResult.getErrorMessage());
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        WmNews wmNews = wmNewsResult.getData();
        if (wmNews == null) {
            log.error("自动审核失败，未查询到自媒体文章信息  wmNewsId:{}",wmNewsId);
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //判断文章状态是否为4或8（审核通过）并判断发布时间是否小于等于当前时间
        Short status = wmNews.getStatus();
        if ((status == WmNews.Status.ADMIN_SUCCESS.getCode() || status == WmNews.Status.SUCCESS.getCode())
        && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {

            publishArticle(wmNews);
            return;
        }
        //        调用发布文章方法
        //判断文章状态是否为1（待审核）  进入审核
        if (status == WmNews.Status.SUBMIT.getCode()) {
            //抽取文章中所有的文本内容和所有的图片URL集合  Map<String  Object>  content 内容  images List<String>
            Map<String,Object> contentAndImageResult = handleTextAndImages(wmNews);
            //敏感词审核   失败  修改文章状态（2）
            boolean isSensivice = handleSensitive((String)contentAndImageResult.get("content"),wmNews);
            if (!isSensivice) return;
            log.info("自管理敏感词审核方法被调用，审核通过=========");
            //阿里云的文本审核  失败 状态2  不确定 状态3
            boolean isTextScan = handleTextScan((String)contentAndImageResult.get("content"),wmNews);
            if (!isTextScan) return;
            log.info("阿里云文本审核通过 ===========");
            //阿里云的图片审核  失败 状态2  不确定 状态3
            Object images = contentAndImageResult.get("images");
            if (images != null) {
                boolean isImageScan =handleImageScan((List<String>) images,wmNews);
                if (!isImageScan) return;
                log.info("阿里云图片审核通过 ===========");
            }
            //判断文章发布时间是否大于当前时间  状态8
            if (wmNews.getPublishTime().after(new Date())){
                updateWmNews(wmNews,WmNews.Status.SUCCESS.getCode(),"审核成功");
                return;
            }
            //发布文章
            publishArticle(wmNews);
        }

    }


    @Autowired
    GreenImageScan greenImageScan;

    /**
     * 阿里云 图片审核
     * @param images
     * @return
     */
    private boolean handleImageScan(List<String> images,WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenImageScan.imageUrlScan(images);
            String suggestion = (String)map.get("suggestion");
            switch (suggestion){
                case "block":
                    updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"图片中存在违规信息，审核失败");
                    flag = false;
                    break;
                case "review":
                    updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"图片中有不确定内容，转为人工审核");
                    flag = false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云 图片审核出现异常  原因：{}",e.getMessage());
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"阿里云内容服务异常，转为人工审核");
            flag = false;
        }
        return flag;
    }
    @Autowired
    GreenTextScan greenTextScan;

    /**
     * 阿里云  文本检测
     * @param content block ：状态2   review ：状态3    异常：状态3
     * @param wmNews
     * @return
     */
    private boolean handleTextScan(String content, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String)map.get("suggestion");
            switch (suggestion){
                case "block":
                    updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"文本中存在违规信息，审核失败");
                    flag = false;
                    break;
                case "review":
                    updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"文本中有不确定内容，转为人工审核");
                    flag = false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云 文本审核出现异常  原因：{}",e.getMessage());
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"阿里云内容服务异常，转为人工审核");
            flag = false;
        }
        return flag;
    }

    @Autowired
    AdSensitiveMapper adSensitiveMapper;

    /**
     * 基于DFA检查内容是否包含敏感词
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleSensitive(String content, WmNews wmNews) {
        boolean flag = true;
        //查询出数据库中的敏感词
        List<String> allSensitives = adSensitiveMapper.findAllSensitives();

        //将敏感词集合转发DFA数据模型
        SensitiveWordUtil.initMap(allSensitives);

        //检查敏感词
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(content);
        if (resultMap != null && resultMap.size() > 0) {
            updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"内容中包含敏感词："+ resultMap);
            flag = false;
        }
        return flag;
    }

    /**
     * 修改文章状态
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);

        ResponseResult responseResult = wemediaFeign.updateWmNews(wmNews);

        if (responseResult.getCode().intValue() != 0) {
            log.error("远程调用修改自媒体文章接口出错，原因：{}    参数：{}",responseResult.getErrorMessage(),wmNews);
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR,responseResult.getErrorMessage());
        }
    }

    /**
     * 抽取文章中所有的文本内容和所有图片的URL路径
     * @param wmNews content  type：text    title
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        String contentJson = wmNews.getContent();
        if (StringUtils.isBlank(contentJson)) {
            log.error("自动审核文章失败，文章内容为空：");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID,"文章内容为空");
        }
        List<Map> contentMaps = JSONArray.parseArray(contentJson, Map.class);
        //抽取文章中所有文本
        String content = contentMaps.stream()
                .filter(map -> "text".equals(map.get("type")))
                .map(map -> (String) map.get("value"))
                .collect(Collectors.joining("_hmtt_"));
        content = content + "_hmtt_" + wmNews.getTitle();


        //抽取文章中所有图片  content : 全路径      images  ：文件名称 + 访问前缀
        List<String> imageList = contentMaps.stream()
                .filter(map -> "image".equals(map.get("type")))
                .map(map -> (String) map.get("value"))
                .collect(Collectors.toList());

        if (StringUtils.isNotBlank(wmNews.getImages())) {
            //按照逗号 切割封面字符串 得到数组 基于数组得到stream 将每一条数据都拼接一个前缀 收集成集合
            List<String> urls = Arrays.stream(wmNews.getImages().split(","))
                    .map(url -> webSite + url)
                    .collect(Collectors.toList());
                imageList.addAll(urls);
        }

        //去重
        imageList.stream().distinct().collect(Collectors.toList());
        Map result = new HashMap();
        result.put("content",content);
        result.put("images",imageList);
        return result;
    }

    /**
     * 发布文章的方法
     * @param wmNews
     */
    private void publishArticle(WmNews wmNews) {
        //远程调用articleFeign接口  保存3张表的数据，保存成功获取返回的articleId
        Long articleId = saveArticle(wmNews);

        //修改wmNews  设置和article的关联 ，修改状态为9
        wmNews.setArticleId(articleId);
        updateWmNews(wmNews,WmNews.Status.PUBLISHED.getCode(),"发布成功");
        //System.out.println("发布文章==========");
        log.info("文章审核通过，并发布成功 关联的文章id===========",articleId);
    }



    @Autowired
    ChannelMapper channelMapper;

    @Autowired
    ArticleFeign articleFeign;
    /**
     * 保存三张表
     * @param wmNews
     * @return
     */
    private Long saveArticle(WmNews wmNews) {
        //封装articleDto
        ArticleDto articleDto = new ArticleDto();
        //拷贝属性
        BeanUtils.copyProperties(wmNews,articleDto);
        articleDto.setId(wmNews.getArticleId());
        /*if (wmNews.getArticleId() != null) {
            articleDto.setId(wmNews.getArticleId());
        }*/
        articleDto.setFlag((byte)0);  //普通文章
        articleDto.setLayout(wmNews.getType());  //布局
        articleDto.setWmUserId(wmNews.getUserId());  //用于获取作者信息
        AdChannel channel = channelMapper.selectById(wmNews.getChannelId());
        articleDto.setChannelName(channel.getName());
        //远程调用文章接口  articleFeign.saverticle(articleDto)
        ResponseResult<Long> saveResult = articleFeign.saveArticle(articleDto);
        if (saveResult.getCode().intValue() != 0) {

            log.error("远程调用保存文章方法失败  原因：{}    参数：{}",saveResult.getErrorMessage(),articleDto);
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        return saveResult.getData();  //返回文章id
    }
}
